#include "DiskController.h"
#include <sys/statfs.h>
#include <cstring>
#include "log.h"
#include <dirent.h>
#include <unistd.h>
#include "Util/logc.h"
#include <sys/stat.h>
namespace fs = std::filesystem;

DiskController::Ptr DiskController::instance(){
    static std::shared_ptr<DiskController> ptr = std::make_shared<DiskController>();
    return ptr;
}


bool DiskController::getDiskSpaceInfo(const std::string& path_str, unsigned long long& used_space, unsigned long long& total_space) {
    if(!isMountPath(path_str)){
        LOG_PrintError("path: %s is not a mount dir\n", path_str.c_str());
        return false;
    }
    /// 用于获取磁盘剩余空间
	struct statfs diskInfo;
    if (statfs(path_str.c_str(), &diskInfo) != 0) {
        LOG_PrintError("statfs call failed with error: %s\n", strerror(errno));
    }

	unsigned long long blocksize                = diskInfo.f_bsize;	//每个block里包含的字节数
	unsigned long long totalsize                = blocksize * diskInfo.f_blocks; 	//总的字节数，f_blocks为block的数目

	//printf("Total_size = %llu B                 = %llu KB = %llu MB = %llu GB\n", 
	//	                                            totalsize, totalsize>>10, totalsize>>20, totalsize>>30);
	
	unsigned long long freeDisk                 = diskInfo.f_bfree * blocksize;	//剩余空间的大小
	unsigned long long availableDisk            = diskInfo.f_bavail * blocksize; 	//可用空间大小
	//printf("Disk_free = %llu MB                 = %llu GB\nDisk_available = %llu MB = %llu GB\n", 
	//	                                            freeDisk>>20, freeDisk>>30, availableDisk>>20, availableDisk>>30);

    used_space = availableDisk;
    total_space = totalsize;
	return true;
}



uintmax_t DiskController::calculateFolderSize(const std::string folderPath) {
    if (!fs::exists(folderPath) || !fs::is_directory(folderPath)) {
        LOG_PrintError("Folder does not exist or is not a directory.\n");
        return 0;
    }

    uintmax_t size = 0;
    
    try {
        for (const auto& entry : fs::directory_iterator(folderPath)) {
            if (fs::is_regular_file(entry)) {
                size += fs::file_size(entry);
            }
        }
    } catch (const fs::filesystem_error& e) {
        LOG_PrintError("Error accessing folder: %s\n", e.what());
        return 0;
    }
    return size;
}

/**
 * 判断当前u盘是否插入
*/
bool DiskController::uDiskLoad(){
    return isMountPath(AIR_UDISK_PATH);
}

bool DiskController::setRealTimeRootPath(){
    #ifdef MODEL_AIR
        if(uDiskLoad()){
            //这里U盘如果
            m_savePath = AIR_UDISK_PATH;	
        }else{
            m_savePath = AIR_FLASH_PATH;	
        }
    #else
        m_savePath = ROOMS_SD_PATH;
    #endif
    //LOG_PrintWarn("m_savePath : %s      isMountPath(m_savePath): %d\n", m_savePath.c_str(),   isMountPath(m_savePath));
    return isMountPath(m_savePath);
}

bool DiskController::getRealTimeRootPath(std::string &path){
    if(m_savePath.empty() && !setRealTimeRootPath()){
       return false;
    }
    path = m_savePath;
    return true;
}

bool DiskController::getRealTimeBusinessPath(std::string subPath,std::string &path){
    path = m_savePath + subPath;
    return true;
}



bool DiskController::clearStreamerFiles(std::string subPath){
    std::string deletePath = m_savePath + subPath;
   
    return removeFilesInDirectory(deletePath.c_str());
}


bool DiskController::isMountPath(std::string path){
    std::lock_guard<std::mutex> lock(m_diskMountLock);
    FILE *fp = fopen("/proc/mounts", "r");
    if (fp == NULL) {
        LOG_PrintError("Error opening /proc/mounts");
        return false;
    }
    char line[256] = {0};
    char mount_point[256] = {0};
    int found = 0;
    while (fgets(line, sizeof(line), fp) != NULL) {
        if (sscanf(line, "%*s %s", mount_point) != 1) {
            continue;
        }

        if (strcmp(mount_point, path.c_str()) == 0) {
            found = 1;
            break;
        }
    }
    fclose(fp);
    if(!found){
        //LOG_PrintError("path %s SD card not load!!\n", path.c_str());
        return false;
    }
    return true;
}

bool DiskController::removeFilesInDirectory(const char* directoryPath) 
{
    if(!directoryPath || access(directoryPath, F_OK) != 0)
    {
        return true; //文件不能访问不用清除
    }
    
    DIR *dir = NULL;
    struct dirent *entry;

    dir = opendir(directoryPath);
    if (dir == NULL) 
    {
        errorf("Error opening directory\n");
        return false;
    }

    char filePath[512];
    while ((entry = readdir(dir)) != NULL) 
    {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        memset(filePath, 0, sizeof(filePath));
        sprintf(filePath, "%s/%s", directoryPath, entry->d_name);
        
        if (remove(filePath) != 0) {
            errorf("Error deleting file\n");
            closedir(dir);
            return false;
        }
    }

    closedir(dir);

    return true;
}



bool DiskController::createFileIfNotExists(const std::string& filename) {
    std::ifstream file(filename);
    if (file.is_open()) {
        file.close(); // 关闭文件描述符
        return true; // 文件已存在
    } else {
        // 获取文件所在目录
        size_t pos = filename.find_last_of("/");
        std::string dir = filename.substr(0, pos);
        // 如果目录不存在，则创建目录
        if (mkdir(dir.c_str(), 0777) == -1 && errno != EEXIST) {
            LOG_PrintError("cannot creat dir %s\n", dir.c_str());
            return false; // 目录创建失败
        }
        std::ofstream newFile(filename);
        if (newFile.is_open()) {
            newFile.close(); // 关闭文件描述符
            return true; // 文件创建成功
        } else {
            LOG_PrintError("cannot to create file: %s\n", filename.c_str());
            return false; // 文件创建失败
        }
    }
}



